package com.eagle.nenaboot.server;

import com.eagle.nenaboot.common.codec.PacketDecoder;
import com.eagle.nenaboot.common.codec.PacketEncoder;
import com.eagle.nenaboot.common.codec.Spliter;
import com.eagle.nenaboot.server.core.handler.ProxyHandler;
import com.eagle.nenaboot.server.core.handler.ServerHandler;
import com.eagle.nenaboot.server.core.net.TcpServer;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import io.netty.handler.timeout.IdleStateHandler;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * @author eagle liu
 * @since 2020/3/13 21:14
 */
@SpringBootApplication
@ComponentScan(basePackages = {"com.eagle.nenaboot"})
@Slf4j
public class ServerApp {


    public static void main(String[] args) {
        SpringApplication.run(ServerApp.class, args);

        //服务端
        TcpServer tcpServer = new TcpServer(10240);
        tcpServer.bind( new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel nioSocketChannel) {
                //粘包拆包
                nioSocketChannel.pipeline().addLast(new Spliter());
                //解码
                nioSocketChannel.pipeline().addLast(new PacketDecoder());
                // 编码
                nioSocketChannel.pipeline().addLast(new PacketEncoder());
				/**
				 * 心跳处理
				 * 心跳是在TCP长连接中，客户端和服务端定时向对方发送数据包通知对方自己还在线，
				 * 保证连接的有效性的一种机制
				 * 在服务器和客户端之间一定时间内没有数据交互时, 即处于 idle 状态时,
				 * 客户端或服务器会发送一个特殊的数据包给对方, 当接收方收到这个数据报文后,
				 * 也立即发送一个特殊的数据报文, 回应发送方, 此即一个 PING-PONG 交互. 自然地,
				 * 当某一端收到心跳消息后, 就知道了对方仍然在线, 这就确保 TCP 连接的有效性.
				 */
                nioSocketChannel.pipeline().addLast(new IdleStateHandler(60, 30, 0));
                // 处理器
                nioSocketChannel.pipeline().addLast(new ServerHandler());
            }
        });

        //代理端
        TcpServer proxyServer = new TcpServer(80);
        proxyServer.bind(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel nioSocketChannel) {
                // 处理器
                nioSocketChannel.pipeline().addLast(new ByteArrayDecoder(), new ByteArrayEncoder(), new ProxyHandler());
            }
        });

		log.info("nena-boot started successfully.");
    }
}
